from Bases import BaseObject, ChildGroup
from baseview import BaseView
from ..bases import widgets
from .. import editors
#from ..bases import clutter_bases
#from DeviceSystem.Groups.AttributeGroup import ProxyGroup
from DeviceSystem.Groups.DeviceGroup import DeviceGroup
from modifiers.snapshot import Stack

class DeviceControlView(BaseView):
    topwidget_name = 'Device Control'
    topwidget_cls = widgets.HPane
    def __init__(self, **kwargs):
        self.topwidget = widgets.VBox()
        super(DeviceControlView, self).__init__(**kwargs)
        self.DeviceSystem = self.MainController.DeviceSystem
        self.device_editor = None
        
        vbox = widgets.VBox()
        self.add_editor(DeviceTable, 'device_table')
        self.device_table.connect('selection_changed', self.on_table_selection_changed)
        vbox.pack_start(self.device_table.topwidget, expand=True)
        
        self.add_editor(GroupTable, 'group_table')
        self.group_table.connect('selection_changed', self.on_table_selection_changed)
        vbox.pack_start(self.group_table.topwidget, expand=True)
        self.topcontainer.pack_start(vbox, expand=True)
        
        #self.selected_controls = SelectedDeviceControl(MainController=self.MainController)
        l = [self.device_table, self.group_table]
        tables = dict(zip([t.topwidget_label for t in l], l))
        self.add_editor(SelectedDeviceControl, 'selected_controls', tables=tables)
        self.topcontainer.pack_start(self.selected_controls.topwidget, expand=True)
        
        self.topwidget.show_all()
        
    def unlink(self):
        super(DeviceControlView, self).unlink()
        #self.selected_controls.unlink()
        
        
    def on_table_selection_changed(self, **kwargs):
        table = kwargs.get('table')
        if table.selected_object:
            for t in [self.device_table, self.group_table]:
                if t != table:
                    t.selected_object = None
        
class ObjectTable(editors.EditorBase):
    def init_editor(self, **kwargs):
        self.register_signal('selection_changed')
        self.DeviceSystem = self.MainController.DeviceSystem
        self._selected_object = None
        self.table = widgets.Table(columns=4, obj_sort_attr='Index')
        self.device_controls = ChildGroup(name='device_controls')
        scrwin = widgets.ScrolledWindow()
        scrwin.pack_start(self.table, expand=True)
        self.topwidget.pack_start(scrwin, expand=True)
        
        for obj in self.ChildGroup.indexed_items.itervalues():
            control = self.build_control(obj)
        self.ChildGroup.connect('child_added', self.on_ChildGroup_child_added)
        self.ChildGroup.connect('child_removed', self.on_ChildGroup_child_removed)
        
    def unlink(self):
        for control in self.device_controls.itervalues():
            control.unlink()
        self.ChildGroup.unbind(self.on_ChildGroup_child_added, self.on_ChildGroup_child_removed)
        super(ObjectTable, self).unlink()
        
    @property
    def selected_object(self):
        return self._selected_object
    @selected_object.setter
    def selected_object(self, value):
        #do_emit = False
        #if not self.selected_object or not value:
        #    do_emit = True
        self._selected_object = value
        for control in self.device_controls.itervalues():
            control.update_selection()
        #if do_emit:
        self.emit('selection_changed', table=self)
    
    def build_control(self, device):
        #if device.saved_class_name == 'PatchedDevice':
        control = self.make_child_editor(self.control_cls, device.id, device=device, table=self)
        self.table.add_object(control)
        #key = getattr(device, self.table_sort_attr)
        self.device_controls.add_child(existing_object=control)
        control.bind(Index=self.on_Index_changed)
        control.topwidget.show_all()
        self.topwidget.queue_resize()
        return control
        
    def on_object_selection_changed(self, **kwargs):
        control = kwargs.get('control')
        if kwargs.get('state'):
            self.selected_object = control.device
            
#    def on_device_num_update(self, **kwargs):
#        device = kwargs.get('device')
#        value = kwargs.get('value')
#        old = kwargs.get('old')
#        if value not in self.device_controls:
#            control = self.device_controls.get(old)
#            if not control:
#                self.build_control(device)
#            else:
#                self.device_controls.update({value:control})
#                del self.device_controls[old]
#                self.table.update_child_objects()

    def on_Index_changed(self, **kwargs):
        obj = kwargs.get('obj')
        self.table.add_object(obj)
        self.topwidget.queue_resize()
        #self.table.update_child_objects()
        
            
    def on_ChildGroup_child_added(self, **kwargs):
        obj = kwargs.get('obj')
        control = self.build_control(obj)
        
    def on_ChildGroup_child_removed(self, **kwargs):
        obj = kwargs.get('obj')
        i = obj.Index
        control = self.device_controls.get(i)
        if control:
            control.unlink()
            self.table.remove_child_object(i)
            #w = control.topwidget
            #w.get_parent().remove(w)
            self.device_controls.del_child(control)
        
    
class DeviceTable(ObjectTable):
    topwidget_label = 'Devices'
    #table_sort_attr = 'device_num'
    def init_editor(self, **kwargs):
        self.control_cls = DeviceControl
        self.ChildGroup = self.DeviceSystem.PatchedDevices
        super(DeviceTable, self).init_editor(**kwargs)
        
class GroupTable(ObjectTable):
    topwidget_label = 'Groups'
    #table_sort_attr = 'Index'
    def init_editor(self, **kwargs):
        self.control_cls = GroupControl
        self.ChildGroup = self.MainController.Groups
        super(GroupTable, self).init_editor(**kwargs)
        
class ObjectControl(BaseObject):
    _Properties = {'selected':dict(default=False, fget='_selected_getter', fset='_selected_setter')}
    def __init__(self, **kwargs):
        self._selected = False
        super(ObjectControl, self).__init__(**kwargs)
        self.register_signal('device_num_update')
        self.MainController = kwargs.get('MainController')
        self.table = kwargs.get('table')
        self._Index_validate_default = True
        self.Index = self.device.Index
        self._Index_validate_default = False
        #self.device_group = self.MainController.Selection
        self.topwidget = widgets.Frame(label=str(self.Index), font_scale=.75)
        self.lbl_name = widgets.Label(self.device.name, font_scale=.75)
        self.lbl_name.set_property('width-chars', 10)
        self.topwidget.pack_start(self.lbl_name)
        self.widgets = {}
        dimmer = self.deviceGroups.get('Dimmer')
        if dimmer:
            widget = widgets.Label(str(dimmer.value))
            for k in ['width-chars', 'max-width-chars']:
                widget.set_property(k, 3)
            dimmer.bind(value=self.on_dimmer_group_value_changed)
            self.topwidget.pack_start(widget)
            self.widgets.update({'Dimmer':widget})
        color = self.deviceGroups.get('Color')
        if color:
            widget = widgets.ColorBtn(Property=(color, 'value'))
            self.topwidget.pack_start(widget.topwidget)
            self.widgets.update({'Color':widget})
        self.btn_select = widgets.ToggleBtn(label='Select', Property=(self, 'selected'))
        #self.device_group.connect('member_update', self.btn_select.on_object_value_changed)
        self.topwidget.pack_start(self.btn_select.widget)
        self.topwidget.show_all()
        
        self.device.bind(property_changed=self.on_device_property_changed, 
                         Index=self.on_device_Index_changed)
        
    def unlink(self):
        for widget in self.widgets.itervalues():
            widget.unlink()
        #self.device_group.disconnect(callback=self.btn_select.on_object_value_changed)
        self.device.unbind(self)#.on_device_Index_changed, self.on_device_property_changed)
        dimmer = self.deviceGroups.get('Dimmer')
        if dimmer:
            #dimmer.disconnect(callback=self.on_dimmer_group_value_changed)
            dimmer.unbind(self)#.on_dimmer_group_value_changed)
        super(ObjectControl, self).unlink()
        
    def on_dimmer_group_value_changed(self, **kwargs):
        value = int(kwargs.get('value'))
        self.widgets['Dimmer'].set_text(str(value))
        
    def _selected_getter(self):
        return self.table.selected_object == self.device
    def _selected_setter(self, value):
        if not value and self.selected:
            self.table.selected_object = None
        elif value:
            self.table.selected_object = self.device
            
#    @property
#    def selected(self):
#        return self.table.selected_object == self.device
#    @selected.setter
#    def selected(self, value):
#        if not value and self.selected:
#            self.table.selected_object = None
#        elif value:
#            self.table.selected_object = self.device
        
    @property
    def id(self):
        return self.device.id
        
    def update_selection(self):
        self.btn_select.on_Property_value_changed()
        
    def on_device_property_changed(self, **kwargs):
        prop = kwargs.get('Property')
        if prop.name == 'name':
            self.lbl_name.set_text(self.device.name)
        
    def on_device_Index_changed(self, **kwargs):
        value = kwargs.get('value')
        self.topwidget.set_label(str(value))
        self.Index = value
        
class DeviceControl(ObjectControl):
    def __init__(self, **kwargs):
        self.device = kwargs.get('device')
        self.deviceGroups = self.device.Groups
        super(DeviceControl, self).__init__(**kwargs)
        
class GroupControl(ObjectControl):
    def __init__(self, **kwargs):
        self.device = kwargs.get('device')
        self.deviceGroups = self.device.AttributeGroups
        super(GroupControl, self).__init__(**kwargs)
        
class SelectedDeviceControl(editors.EditorBase):
    topwidget_label = 'Selected Device Controls'
    def init_editor(self, **kwargs):
        self._selected_object = None
        self.tables = kwargs.get('tables')
        for t in self.tables.itervalues():
            t.connect('selection_changed', self.on_selection_changed)
        #self.DeviceSystem = self.MainController.DeviceSystem
        #self.topwidget = widgets.VBox()
        self.control_container = widgets.HBox()
        #self.device_group = self.MainController.Selection
        self.controls = {}
        self.param_group_controls = {}
        self.param_group_pages = {}
        self.param_group_tables = {}
        self.groups = set()
        self.proxy_groups = {}
        self.dummy_attribs = {}
        
        self.build_controls()
        self.topwidget.pack_start(self.control_container, expand=True)
        #self.topwidget.show_all()
        
    @property
    def selected_object(self):
        return self._selected_object
    @selected_object.setter
    def selected_object(self, value):
        if value:
            if value == self._selected_object:
                return
            self._selected_object = value
            if value.base_class == 'Group':
                attr_groups = value.AttributeGroups
            else:
                attr_groups = value.Groups
            for key, val in self.controls.iteritems():
                group = attr_groups.get(key)
                if group:
                    val.Property = (group, 'value')
                else:
                    val.Property = None
            self.clear_param_group_controls()
            for param_group in value.ParameterGroups.itervalues():
                self.add_param_group_controls(param_group=param_group)
        else:
            self._selected_object = None
            for c in self.controls.itervalues():
                c.Property = None
            self.clear_param_group_controls()
        
    def build_controls(self):
        w = widgets.VSlider(label='Dimmer')
        self.control_container.pack_start(w.topwidget)
        self.controls['Dimmer'] = w
        
        vbox = widgets.VBox()
        
        w = widgets.ColorSelection(label='Color')
        vbox.pack_start(w.topwidget, expand=True)
        self.controls['Color'] = w
        
        w = widgets.XYSlider(label='Position')
        vbox.pack_start(w.topwidget, expand=True)
        self.controls['Position'] = w
        
        self.control_container.pack_start(vbox)
        
        #scr_win = widgets.ScrolledWindow()
        #self.param_group_container = widgets.Table(columns=4)
        self.param_group_container = widgets.Notebook()
        self.add_param_notebook_page('Misc')
        #scr_win.pack_start(self.param_group_container)
        self.control_container.pack_start(self.param_group_container, expand=True)
        
        #for grkey, grval in self.device_group.ParameterGroups.iteritems():
        #    self.add_param_group_controls(param_group=grval)
        #self.device_group.connect('new_parameter_group', self.add_param_group_controls)
        
        
    def unlink(self):
        super(SelectedDeviceControl, self).unlink()
        self.selected_object = None
        #self.device_group.disconnect(callback=self.add_param_group_controls)
        for d in [self.controls, self.param_group_controls]:
            for control in d.itervalues():
                control.unlink()
                
    def add_param_group_controls(self, **kwargs):
        group = kwargs.get('param_group')
        if group.id not in self.param_group_controls:
            control = ParamGroupControls(group=group)
            if not group.categories:
                self.param_group_tables['Misc'].pack_start(control.topwidget, expand=True)
            else:
                for c in group.categories.itervalues():
                    tbl = self.param_group_tables.get(c.name)
                    if not tbl:
                        tbl = self.add_param_notebook_page(c.name)
                    tbl.pack_start(control.topwidget, expand=True)
                    
            #self.param_group_container.pack_start(control.topwidget, expand=True)
            self.param_group_controls.update({group.id:control})
            control.topwidget.show_all()
        
    def add_param_notebook_page(self, name):
        scr_win = widgets.ScrolledWindow()
        tbl = widgets.Table(columns=4)
        scr_win.pack_start(tbl, expand=True)
        self.param_group_container.add_page(widget=scr_win, label=name)
        self.param_group_pages[name] = scr_win
        self.param_group_tables[name] = tbl
        scr_win.show_all()
        return tbl
            
    def clear_param_group_controls(self):
        for c in self.param_group_controls.itervalues():
            c.unlink()
            #self.param_group_container.remove(c.topwidget)
            #c.topwidget.get_parent().remove(c.topwidget)
        #tbl = self.param_group_container
        #print 'param_group_container children=%s, loc=%s' % (tbl._child_widgets, tbl._child_locations)
        #self.param_group_container.clear()
        for key, val in self.param_group_pages.iteritems():
            self.param_group_container.remove(val)
        self.param_group_pages.clear()
        self.param_group_tables.clear()
        self.param_group_controls.clear()
        self.add_param_notebook_page('Misc')
            
    def clear_all(self):
        for control in self.controls.itervalues():
            control.unlink()
            self.control_container.remove(control.topwidget)
        self.groups.clear()
        self.proxy_groups.clear()
        self.controls.clear()
        
    def on_selection_changed(self, **kwargs):
        table = kwargs.get('table')
        if table.selected_object:
            self.selected_object = table.selected_object
            return
        flag = False
        for t in self.tables.itervalues():
            if t.selected_object:
                flag = True
        if not flag:
            self.selected_object = None
    
class TestObj(BaseObject):
    def __init__(self, **kwargs):
        super(TestObj, self).__init__(**kwargs)
        self.register_signal('value_changed')
        self.name = kwargs.get('name')
        self._value = 0.
        self.max = 1.
        self.min = -1.
    @property
    def value(self):
        return self._value
    @value.setter
    def value(self, value):
        if value != self.value:
            self._value = value
            print self.name, self.value
            self.emit('value_changed', value=value)

class ParamGroupControls(BaseObject):
    def __init__(self, **kwargs):
        super(ParamGroupControls, self).__init__(**kwargs)
        self.group = kwargs.get('group')
        self.fader = None
        names = ['id', 'Name']
        
        self.param_list = widgets.TreeList(name=self.group.attribute_name, column_names=names, 
                                           list_types=[str, str], column_order=[1])
        self.update_param_list()
        self.topwidget = self.param_list.topwidget
        
        self.on_parameter_changed()
        key = self.param_list.current_selection
        if key:
            self.on_list_selection_changed(key=key)
        self.param_list.connect('selection_changed', self.on_list_selection_changed)
        
        #self.param_list.set_current_selection(key=self.group.find_name_from_id())
        
        
        
        self.group.connect('new_parameter', self.update_param_list)
        self.group.connect('parameter_changed', self.on_parameter_changed)
        
    def unlink(self):
        self.group.disconnect(callback=self.update_param_list)
        self.group.disconnect(callback=self.on_parameter_changed)
        
    def update_param_list(self, **kwargs):
        for key in self.group.indexed_parameters.iterkeys():
            self.param_list.update({key:key})
    
    def on_parameter_changed(self, **kwargs):
        #key = kwargs.get('id')
        key = self.group.active_parameter
        #print 'param parameter_changed:', key
        if not key:
            return
        #key = self.group.parameter_obj[param].id
        if self.param_list.current_selection != key:
            self.param_list.set_current_selection(key=key)
        param = self.group.parameter_obj[key]
        self.build_parameter_fader(param)
    
    def on_list_selection_changed(self, **kwargs):
        name = kwargs.get('key')
        #print 'param list_sel_change:', name
        #name = self.group.find_name_from_id(key)
        if self.group.active_parameter != name:
            self.group.active_parameter = name
            
    def build_parameter_fader(self, param):
        if self.fader is not None:
            self.fader.unlink()
            w = self.fader.topwidget
            w.get_parent().remove(w)
            #self.topwidget.remove(self.fader.topwidget)
        val_max = param.value_max - param.value_min
        #print 'max=', val_max
        #print 'build_fader: %s, value=%s' % (param, param.value)
        self.fader = widgets.HSlider(Property=(param, 'value'), offset_value_range=True)#, adj_kwargs = {'lower':0, 'upper':val_max})
        self.topwidget.pack_start(self.fader.topwidget)
        self.fader.topwidget.show_all()

class Palette(BaseObject):
    button_types = {'button':widgets.Button, 'color':widgets.ColorBtn}
    def __init__(self, **kwargs):
        super(Palette, self).__init__(**kwargs)
        self.name = kwargs.get('name', '')
        self.grid_size = kwargs.get('grid_size', (8, 2))
        self.button_type = kwargs.get('button_type', 'button')
        self.buttons = []
        table = widgets.Table(columns=self.grid_size[0], rows=self.grid_size[1], homogeneous=True)
        self.topwidget = widgets.Expander(label=self.name, topwidget=table)
        self.build_buttons()
        self.topwidget.show_all()
    def build_buttons(self):
        cls = self.button_types.get(self.button_type)
        i = 0
        for y in range(self.grid_size[1]):
            for x in range(self.grid_size[0]):
                i += 1
                btn = cls(label=str(i))
                btn.connect('clicked', self.on_button_clicked, i)
                self.topwidget.attach(btn, x, x+1, y, y+1)
                self.buttons.append(btn)
    def on_button_clicked(self, btn, index):
        print 'clicky:', index


UI_VIEW = DeviceControlView
